package libs

import (
	"bytes"
	"fmt"
	"github.com/goccy/go-json"
	"image"
	"image/draw"
	"image/jpeg"
	"io/fs"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

// FileIsNotExist
// path 文件路径
// 返回值true 文件不存在, false 文件存在
func FileIsNotExist(path string) bool {
	_, err := os.Stat(path)
	return os.IsNotExist(err)
}

// CreateDetect 不存在则创建文件夹
func CreateDetect(path string) error {
	b := FileIsNotExist(path)
	if !b {
		return nil
	}
	//重新创建
	e := os.MkdirAll(path, 0755)
	if e != nil {
		return e
	}
	return nil
}

// GetFolderName 获取文件夹以及子文件夹名称
// destDir 文件夹位置
// isFirst 一级文件夹 默认false获取全部文件夹
func GetFolderName(destDir string, isFirst int) (list []string, err error) {
	list = make([]string, 0)
	err = filepath.WalkDir(destDir, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		if d.IsDir() && path != destDir { // 排除初始目录及其子目录"an hui"
			parentPath := filepath.Dir(path)
			if isFirst == 1 { //一级文件夹
				if parentPath == destDir {
					list = append(list, path)
				}
			} else if isFirst == 2 { //不包含一级文件夹
				if parentPath != destDir {
					list = append(list, path)
				}
			} else { //全部文件夹
				list = append(list, path)
			}
		}
		return nil
	})

	return list, err
}

// ReadFile 读取文件中内容
// filePath 文件地址
func ReadFile(filePath string) ([]byte, error) {
	data, err := ioutil.ReadFile(filePath)
	return data, err
}

// CreateFile 创建文件
func CreateFile(filePath string) error {
	b := FileIsNotExist(filePath)
	if !b {
		// 文件不存在，尝试创建它
		file, err := os.Create(filePath)
		if err != nil {
			return fmt.Errorf("create file Fail : %w", err)
		}
		defer file.Close()
	}
	return nil
}

// WritesAnyToFile 往文件中写入json文件
func WritesAnyToFile(filePath string, data interface{}) error {
	//创建文件
	_ = CreateFile(filePath)

	//写入json文件
	json, err := json.Marshal(data)
	if err != nil {
		return err
	}
	//创建文件
	err = ioutil.WriteFile(filePath, json, 0755)
	if err != nil {
		return fmt.Errorf("写入文件失败：%w", err)
	}
	return nil
}

// MoveFolder 往上一层移动文件夹
func MoveFolder(src string, dest string) error {
	//资源路径：internal\recruit\static\24987\2023\dbf\194561\测试
	//目标路径：internal\recruit\static\24987\2023\move_dbf_tmp\194561
	//将资源路径中的全部文件一级文件夹移动到目标路径中
	//去掉资源路径中的一级文件夹
	//folder 一定要是文件夹才能执行下面动作
	info, err := os.Stat(src)
	if err == nil && info.IsDir() {
		err = filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return fmt.Errorf("去读文件错误：%w", err)
			}

			f := strings.Replace(path, src, "", -1)
			destPath := filepath.Join(dest, f)
			if info.IsDir() {
				// 创建目录（如果不存在）
				err = os.MkdirAll(destPath, 0755)
				if err != nil {
					return ErrorMsg(err, "创建文件夹错误")
				}
			} else {
				err = os.Rename(path, destPath)
				if err != nil {
					return ErrorMsg(err, "创建文件错误")
				}
			}
			return nil
		})

		if err != nil {
			return ErrorMsg(err, "创建文件出错")
		}
		//// 删除源文件夹
		err = os.RemoveAll(src)
		if err != nil {
			return fmt.Errorf("删除文件夹时出错:%w", err)
		}
	}
	return err
}

// GetPathToSlash 文件名称,同一格式/a/b/c/t.txt
func GetPathToSlash(path []string) string {
	return filepath.ToSlash(filepath.Join(path...))
}

// GetUnifiedPath 统一路径名称
func GetUnifiedPath(path string) string {
	return filepath.ToSlash(path)
}

// ConvertImageToJpg 将图片转成jpg格式
func ConvertImageToJpg(inputPath string, outputPath string) error {
	// 打开输入文件
	file, err := os.Open(inputPath)
	if err != nil {
		return fmt.Errorf("打开输入文件错误: %v", err)
	}
	defer file.Close()

	// 解析图像
	img, _, err := image.Decode(file)
	if err != nil {
		return fmt.Errorf("解析图像错误: %v", err)
	}

	// 创建一个新的RGBA图像以便兼容所有源格式
	bounds := img.Bounds()
	rgba := image.NewRGBA(bounds)

	// 将原图绘制到RGBA图像上
	draw.Draw(rgba, bounds, img, image.Point{}, draw.Src)

	// 创建一个缓冲区存放JPEG编码后的数据
	buf := new(bytes.Buffer)

	// 将图像编码为JPEG格式
	err = jpeg.Encode(buf, rgba, &jpeg.Options{Quality: 100}) // 设置质量为100（范围是1-100）
	if err != nil {
		return fmt.Errorf("编码为JPEG格式错误: %v", err)
	}

	// 写入输出文件
	outFile, err := os.Create(outputPath)
	if err != nil {
		return fmt.Errorf("创建输出文件错误: %v", err)
	}
	defer outFile.Close()

	_, err = outFile.Write(buf.Bytes())
	if err != nil {
		return fmt.Errorf("写入输出文件错误: %v", err)
	}

	return nil
}

// AllFilesInDir 获取文件夹下的文件数量
func AllFilesInDir(src string) ([]string, int, error) {
	list := make([]string, 0)
	count := 0
	err := filepath.Walk(src, func(path string, info fs.FileInfo, err error) error {
		if !info.IsDir() { //文件数量
			count++
			list = append(list, path)
		}
		return nil
	})
	return list, count, err
}
